package cn.icanci.loopstack.bic.sdk.burying.aop;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;

/**
 * @author icanci
 * @since 1.0 Created in 2023/09/27 16:25
 */
public class ThreadLocalUtils {
    private static final String                           UK_FORMAT    = "%s#%s#%s";
    private static final String                           USE_CASE_KEY = "$USE_CASE_KEY$";
    private static final String                           CLASS_KEY    = "$CLASS_KEY$";
    private static final String                           METHOD_KEY   = "$METHOD_KEY$";

    private static final ThreadLocal<Map<String, String>> THREAD_LOCAL = ThreadLocal.withInitial(() -> new HashMap<>(3));

    // ======================== use case ======================== 
    public static void setUseCase(String val) {
        THREAD_LOCAL.get().put(USE_CASE_KEY, val);
    }

    public static void removeUseCase() {
        THREAD_LOCAL.remove();
    }

    public static String getUseCase() {
        return THREAD_LOCAL.get().get(USE_CASE_KEY);
    }

    // ======================== class ========================
    public static void setClazz(String val) {
        THREAD_LOCAL.get().put(CLASS_KEY, val);
    }

    public static void removeClazz() {
        THREAD_LOCAL.get().remove(CLASS_KEY);
    }

    public static String getClazz() {
        return THREAD_LOCAL.get().get(CLASS_KEY);
    }
    // ======================== method ========================

    public static void setMethod(String val) {
        THREAD_LOCAL.get().put(METHOD_KEY, val);
    }

    public static void removeMethod() {
        THREAD_LOCAL.get().remove(METHOD_KEY);
    }

    public static String getMethod() {
        return THREAD_LOCAL.get().get(METHOD_KEY);
    }

    public static void fillThreadContext(ProceedingJoinPoint point) {
        try {
            MethodSignature method = (MethodSignature) point.getSignature();
            Method targetMethod = point.getTarget().getClass().getDeclaredMethod(method.getName(), method.getMethod().getParameterTypes());

            String simpleName = point.getTarget().getClass().getSimpleName();
            String methodName = targetMethod.getName();

            ThreadLocalUtils.setClazz(simpleName);
            ThreadLocalUtils.setMethod(methodName);
        } catch (Exception ignore) {

        }
    }

    public static void removeThreadContext() {
        ThreadLocalUtils.removeClazz();
        ThreadLocalUtils.removeMethod();
    }

    // ======================== uk ========================
    public static String getUk() {
        return String.format(UK_FORMAT, getUseCase(), getClazz(), getMethod());
    }
}
